﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Engine;
using Engine.Pathfinding;

namespace Game
{
        class SwarmManager
        {
            public List<Swarm> mSwarmList;

            public SwarmManager()
            {
                mSwarmList = new List<Swarm>();
                mSwarmList.Add(new Swarm());
            }

            public void Update(GameTime _time)
            {
                for(int i = 0; i < mSwarmList.Count; i++)
                {
                    mSwarmList[i].Update(_time);

                    if(mSwarmList[i].mEnemyList.Count < 1)
                    {
                        mSwarmList.Add(new Swarm());
                        mSwarmList.Remove(mSwarmList[i]);
                    }
                }

                
            }

            public void Draw(SpriteBatch spriteBatch, Matrix ViewMatrix, Matrix ProjectionMatrix)
            {
                for(int i = 0; i < mSwarmList.Count; i++)
                {
                    mSwarmList[i].Draw(spriteBatch, ViewMatrix, ProjectionMatrix);
                }
            }

        }

        class Swarm
        {
            public List<Enemy> mEnemyList;
            Vector2 mLeaderPos;
            Vector3 mPlayerPos;
            Queue<Vector3> mSolution;

            public Enemy GetLeader()
            {
                    Enemy aux = new Enemy();
                    for(int i = 0; i < mEnemyList.Count; i++)
                    {
                        if(mEnemyList[i].isLeader)
                        {                            
                            aux = mEnemyList[i];
                        }                        
                    }
                    return aux;
            }

            public Swarm()
            {
                mEnemyList = new List<Enemy>();
                mSolution = new Queue<Vector3>();

                for (int i = 0; i < 20; i++)
                {
                    mEnemyList.Add(new Enemy());
                    mEnemyList.ElementAt(i).Position = new Vector3(-5000 + i * -200, 200, 1600 + i * -100);
                    mEnemyList[i].mModel = ModelDrawer.zombie;                    
                }
                mEnemyList[0].isLeader = true;
            }

            public Swarm(Node _node)
            {
                mEnemyList = new List<Enemy>();
                mSolution = new Queue<Vector3>();

                for (int i = 0; i < 20; i++)
                {
                    mEnemyList.Add(new Enemy());
                    mEnemyList.ElementAt(i).Position = new Vector3((float)_node.Position.X + i * -200, 200, (float)_node.Position.Z + i * -100);
                    mEnemyList[i].mModel = ModelDrawer.zombie;
                }
                mEnemyList[0].isLeader = true;
            }

            public void GetPlayerPos(Vector3 _pos)
            {
                mPlayerPos = _pos;
            }

            Vector3 Alignment(Enemy _b)
            {
                Vector3 pvJ = Vector3.Zero;


                    foreach (Enemy b in mEnemyList)
                    {
                        if (b != _b)
                        {
                            pvJ = pvJ + b.Transform.Forward;
                        }
                    }

                pvJ = pvJ / mEnemyList.Count;

                return ((pvJ - _b.Transform.Forward) / 8);
            }

            Vector3 Separation(Enemy _b)
            {
                Vector3 c = Vector3.Zero;

                    foreach (Enemy b in mEnemyList)
                    {

                        if (b != _b)
                        {
                            if (Vector3.Distance(b.Transform.Position, _b.Transform.Position) < 500)
                            {
                                c = c - (b.Transform.Position - _b.Transform.Position);
                            }
                        }
                    }

                return c;
            }

            Vector3 Cohesion(Enemy _b)
            {
                Vector3 fvPercievedCenter = Vector3.Zero;

                foreach (Enemy b in mEnemyList)
                {
                    if (b != _b)
                    {
                        fvPercievedCenter += b.Transform.Position;
                    }
                }

                fvPercievedCenter /= mEnemyList.Count - 1;

                return (fvPercievedCenter - _b.Transform.Position) / 15;
            }

            public void Draw(SpriteBatch _batch, Matrix _view, Matrix _proj)
            {
                foreach (Enemy b in mEnemyList)
                {
                    b.Draw(_batch, _view, _proj);
                }
            }

            public void Update(GameTime _time)
            {
                Vector3 v1, v2, v3;

                for (int i = 0; i < mEnemyList.Count; i++)
                {
                    if (mEnemyList[i].isLeader)
                    {
                        mLeaderPos.X = mEnemyList[i].Position.X;
                        mLeaderPos.Y = mEnemyList[i].Position.Z;
                    }

                    if (!mEnemyList[i].Life.IsAlive)
                    {
                        //si murio y es el lider
                        if (mEnemyList[i].isLeader)
                        {
                            //seteo un nuevo leader.
                            SetNewLeader();
                        }
                        mEnemyList.Remove(mEnemyList[i]);
                    }

                }

                foreach(Enemy b in mEnemyList)
                   {
                        v1 = Cohesion(b);
                        v2 = Separation(b);
                        v3 = Alignment(b);

                        b.Transform.Translate((v1 * 0.05f + v2 * 0.5f/* + v3*/) / 5);
                        if(b.isLeader)
                        {
                            foreach (Enemy j in mEnemyList)
                            {
                                if(!j.isLeader)
                                    j.Transform.LookAt(b.Transform.Position);
                            }
                        }
                        
                           b.Update(_time, mPlayerPos);
                    }
               }


            void SetNewLeader()
            {
                int futureleader = 0;
                //auxiliar de distancia minima
                float mindist = float.MaxValue;

                //axuiliar de la distancia real
                float bdist = 0.0f;

                for(int i = 0; i < mEnemyList.Count; i++)
                {
                    if(!mEnemyList[i].isLeader)
                    {
                        //la distancia entre B y el lider es:
                        bdist = Vector2.Distance(new Vector2(mEnemyList[i].Position.X, mEnemyList[i].Position.Z), mLeaderPos);

                        //si es menor que "la distancia minima"
                        if (bdist < mindist)
                        {
                            //seteo a este enemigo como el heredero
                            mindist = bdist;
                            futureleader = i;
                    }
                    
                    }
                }
                //finalmente recorri toda la lista, este es el heredero, entonces, es el lider.
                mEnemyList[futureleader].isLeader = true;
            }


        }

}
